#include "measure.h"
extern int class_type ;
#define CLASS_COUNT 15
//调节AD采样率
void adjust_ADSR(u16 sample_rate){//只能是100k，10k，500k，300k，329k，5k，5.12k参数单位是kHz
	switch(sample_rate) {
		case 5:
			// 实际采样率 = 84MHz / ((83+1) * (1999+1)) = 5000 Hz = 5 kHz
			__HAL_TIM_SET_PRESCALER(&htim3, 83);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 1999);
			break;

		case 10:
			// 实际采样率 = 84MHz / ((83+1) * (99+1)) = 10000 Hz = 10 kHz
			__HAL_TIM_SET_PRESCALER(&htim3, 83);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 99);
			break;

		case 100:
			// 实际采样率 = 84MHz / ((83+1) * (9+1)) = 100000 Hz = 100 kHz
			__HAL_TIM_SET_PRESCALER(&htim3, 83);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 9);
			break;

		case 300:
			// 实际采样率 = 84MHz / ((27+1) * (9+1)) = 300000 Hz = 300 kHz
			__HAL_TIM_SET_PRESCALER(&htim3, 27);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 9);
			break;

		case 329:
			// 实际采样率 = 84MHz / ((25+1) * (9+1)) ≈ 323.077 kHz (最接近329kHz的配置)
			__HAL_TIM_SET_PRESCALER(&htim3, 25);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 9);
			break;

		case 500:
			// 实际采样率 = 84MHz / ((25+1) * (5+1)) ≈ 538.46 kHz (最接近500kHz的配置)
			__HAL_TIM_SET_PRESCALER(&htim3, 25);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 5);
			break;

		case 512:
			// 实际采样率 = 84MHz / ((25+1) * (5+1)) ≈ 538.46 kHz (最接近512kHz的配置)
			__HAL_TIM_SET_PRESCALER(&htim3, 25);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 5);
			break;

		case 1024:
			// 实际采样率 = 84MHz / ((12+1) * (5+1)) ≈ 1076.92 kHz (最接近1024kHz的配置)
			__HAL_TIM_SET_PRESCALER(&htim3, 12);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 5);
			break;

		default:
			// 不支持的采样率，使用默认设置
			__HAL_TIM_SET_PRESCALER(&htim3, 83);
			__HAL_TIM_SET_AUTORELOAD(&htim3, 9);
			break;
	}
}

//AD开始
void ADstart(u16 sample_num){
	//AD开始
	flag_ad_finish = 0;
	if (HAL_ADC_Start(&hadc2) == HAL_OK && HAL_ADC_Start(&hadc3) == HAL_OK && HAL_ADCEx_MultiModeStart_DMA(&hadc1,adc_buf, 3 * sample_num) == HAL_OK)
	{
		HAL_TIM_Base_Start(&htim3);//启动触发定时器
	} else {
		Error_Handler();
	}
	while (flag_ad_finish == 0);//等待AD完成
	//分离三个通道
	u16 i;
	Vout_sum = 0;
	for (i=0;i<sample_num;i++){
		//找Vin最大值和最小值
		ad_Vin[i] = adc_buf[3*i];
		if (ad_Vin[i] > Vin_max)
			Vin_max = ad_Vin[i];
		if (ad_Vin[i] < Vin_min)
			Vin_min = ad_Vin[i];
		//找Iin最大值和最小值
		ad_Iin[i] = adc_buf[3*i+1];
		if (ad_Iin[i] > Iin_max)
			Iin_max = ad_Iin[i];
		if (ad_Iin[i] < Iin_min)
			Iin_min = ad_Iin[i];
		//找Vout最大值和最小值，求和
		ad_Vout[i] = adc_buf[3*i+2];
		if (ad_Vout[i] > Vout_max)
			Vout_max = ad_Vout[i];
		if (ad_Vout[i] < Vout_min)
			Vout_min = ad_Vout[i];
		Vout_sum += ad_Vout[i];
	}
	//找峰峰值
	Vin_Vpp = (Vin_max - Vin_min) * 3300 / 4095;
	Vin_max = 0;
	Vin_min = 0xFFFFFFFF;
	Iin_Vpp = (Iin_max - Iin_min) * 3300 / 4095;
	Iin_max = 0;
	Iin_min = 0xFFFFFFFF;
	Vout_Vpp = (Vout_max - Vout_min) * 3300 / 4095;
	Vout_max = 0;
	Vout_min = 0xFFFFFFFF;
	Vout_av = Vout_sum * 3300 / 4095 / sample_num;
}

void Mea20Delay(void){
	u16 i;
    // 先修改 dds_freq 再传参
    dds_freq = 10;
	AD9851_Write(dds_freq);
	adjust_ADSR(512);//5.12k采样率
	ADstart(512);

	for (i=0;i<512;i++){
		ad_Vin_fft[2*i] = ad_Vin[i];
		ad_Vin_fft[2*i+1] = 0;
		ad_Vout_fft[2*i] = ad_Iin[i];
		ad_Vout_fft[2*i+1] = 0;
	}
	arm_cfft_f32(&arm_cfft_sR_f32_len512,ad_Vin_fft,0,1);
	arm_cfft_f32(&arm_cfft_sR_f32_len512,ad_Vout_fft,0,1);
	phase_diff = 0.6*phase_diff + 0.4*(180 * atan((double)((ad_Vin_fft[3]*ad_Vout_fft[2]-ad_Vin_fft[2]*ad_Vout_fft[3]) / (ad_Vin_fft[2]*ad_Vout_fft[2]+ad_Vin_fft[3]*ad_Vout_fft[3]))) / 3.1415926);
}
//故障检测模式参量采样
void ADstart_detect(void){
	u8 i;
	u32 Vo_sum=0, Vi_sum=0;
	float x = AV_VIN*AV_VOUT;
	//测量10Hz时电压和电流时间差
	Mea20Delay();
	//先测量100Hz和200kHz时的增益，防止电压电流变了
	//100Hz
    dds_freq = 100;
	AD9851_Write(dds_freq);
	adjust_ADSR(10);//10k采样率
	for (i=0;i<6;i++){
		ADstart(100);
		Vo_sum += (u32)Vout_Vpp;
		Vi_sum += (u32)Vin_Vpp;
	}
	Av_100 = (u32)(Vo_sum * x / Vi_sum);
	//200k
	Vo_sum=0;
	Vi_sum=0;
    dds_freq = 200000;
	AD9851_Write(dds_freq);
	adjust_ADSR(329);//329k采样率
	for (i=0;i<6;i++){
		ADstart(500);
		Vo_sum += (u32)Vout_Vpp;
		Vi_sum += (u32)Vin_Vpp;
	}
	Av_200k = (u32)(Vo_sum * x / Vi_sum);
	//测量电压、电流参数
	Vin_Vpp_sum=0;
	Iin_Vpp_sum=0;
	Vout_Vpp_sum=0;
	Vout_av_sum=0;
    dds_freq = 1000;
	AD9851_Write(dds_freq);
	adjust_ADSR(100);//AD采样率调为100k
	for (i=0;i<10;i++){
		ADstart(100);//采样100点
		Vin_Vpp_sum += Vin_Vpp;
		Iin_Vpp_sum += Iin_Vpp;
		Vout_Vpp_sum += Vout_Vpp;
		Vout_av_sum += Vout_av;
	}
	Vin_Vpp = Vin_Vpp_sum / 10;
	Iin_Vpp = Iin_Vpp_sum / 10;
	Vout_Vpp = Vout_Vpp_sum / 10;
	Vout_av = Vout_av_sum / 10;

}


//测量输入电阻
void MeasRi(void){
	u8 i;
	u32 Ri_sum=0;
	float x = 1000.0f*AV_IIN/AV_VIN;

    dds_freq = 1000;
	AD9851_Write(dds_freq);
	adjust_ADSR(100);//AD采样率调为100k
	for (i=0;i<6;i++){
		ADstart(100);//采样100点
		Ri_sum += (u32)(Vin_Vpp*x/Iin_Vpp);
	}
	Ri_mea = (u16)(Ri_sum / 6);
}

//测量输出电阻
void MeaRo(void){
	u32 Vo_unload=0, Vo_load=0;
	u32 R_load = 2000;
	HAL_GPIO_WritePin(Relay_GPIO_Port, Relay_Pin, GPIO_PIN_RESET);//断开继电器，空载
    dds_freq = 1000;
	AD9851_Write(dds_freq);
	adjust_ADSR(100);//AD采样率调为100k

	ADstart(100);//采样100点
	Vo_unload = Vout_Vpp;//空载电压
	HAL_GPIO_WritePin(Relay_GPIO_Port, Relay_Pin, GPIO_PIN_SET);//闭合继电器，带载
	HAL_Delay(10);//等待完全闭合

	ADstart(100);//采样100点
	Vo_load = Vout_Vpp;//带载电压

	Ro_mea = (Vo_unload - Vo_load) * R_load / Vo_load;
	HAL_GPIO_WritePin(Relay_GPIO_Port, Relay_Pin, GPIO_PIN_RESET);//断开继电器，空载
	HAL_Delay(10);//等待完全断开
}

//测量增益
void MeaAv(void){
	u8 i;
	u32 Vo_sum=0, Vi_sum=0;
	float x = AV_VIN*AV_VOUT;

    dds_freq = 1000;
	AD9851_Write(dds_freq);
	adjust_ADSR(100);//AD采样率调为100k
	for (i=0;i<6;i++){
		ADstart(100);//采样100点
		Vo_sum += (u32)Vout_Vpp;
		Vi_sum += (u32)Vin_Vpp;
	}
	Av_mea = (u32)(Vo_sum * x / Vi_sum);
}

//测量三极管放大倍数
void MeaHf(void){
	float Rbe;
	Rbe = (float)Ri_mea*R1_MEA*R2_MEA / (R1_MEA*R2_MEA - Ri_mea*(R1_MEA+R2_MEA));
	beta_HF = (u32)(Av_mea * Rbe / R3_MEA);
}

//测量幅频特性
void MeaAf(void){
	float x = AV_VIN*AV_VOUT;
	u8 i;
	u32 Vo_sum=0, Vi_sum=0;

	if (freq_step == 0){//100Hz
        dds_freq = 100;
		AD9851_Write(dds_freq);
		adjust_ADSR(10);//10k采样率
		for (i=0;i<6;i++){
			ADstart(100);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[0] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 1){//1kHz
        dds_freq = 1000;
		AD9851_Write(dds_freq);
		adjust_ADSR(100);//100k采样率
		for (i=0;i<6;i++){
			ADstart(100);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[1] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 2){//10kHz
        dds_freq = 10000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[2] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 3){//100kHz
        dds_freq = 100000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[3] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 4){//120kHz
        dds_freq = 120000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[4] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 5){//140kHz
        dds_freq = 140000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[5] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 6){//160kHz
        dds_freq = 160000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[6] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 7){//180kHz
        dds_freq = 180000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[7] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
		else if (freq_step == 8){//200kHz
        dds_freq = 200000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[8] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
	else if (freq_step == 9){//1MHz
        dds_freq = 1000000;
		AD9851_Write(dds_freq);
		adjust_ADSR(329);//329k采样率
		for (i=0;i<6;i++){
			ADstart(500);
			Vo_sum += (u32)Vout_Vpp;
			Vi_sum += (u32)Vin_Vpp;
		}
		Av_Afmea[9] = (u32)(Vo_sum * x / Vi_sum);
		freq_step++;
	}
}

//计算上限截止频率
void MeafH(void){
	double x;
	u8 i;
	u32 f[10] = {100,1000,10000,100000,120000,140000,160000,180000,200000,1000000};
	for (i=0;i<9;i++){
		if (Av_Afmea[i] >= Av_Afmea[2]*0.70710678 && Av_Afmea[i+1] < Av_Afmea[2]*0.70710678)
			break;
	}
	x = (20*log10((double)(Av_Afmea[i])/(double)(Av_Afmea[2]*0.70710678)))/(20*log10((double)(Av_Afmea[2]*0.70710678))/(double)(Av_Afmea[i+1]));
	if (fH_mea == MEA_INVALID){
		fH_mea = (u32)(((double)(f[i]) + (double)(f[i+1])*x) / (1+x));
	} else {
		fH_mea = (u32)(0.6*fH_mea + 0.4*(((double)(f[i]) + (double)(f[i+1])*x) / (1+x)));
	}

}

// 计算插值数据（点数调整为276，范围0-275）
void sendAFDispdata(void){
    s32 i;
    // 原始测量点映射到新的276点坐标系
    // 注意：需重新计算各频率点在0-275范围内的位置
    Av_dispdata[0]   = (u8)(20*log10((double)Av_Afmea[0]) * 255 / 50);  // 100Hz
    Av_dispdata[68]  = (u8)(20*log10((double)Av_Afmea[1]) * 255 / 50);  // 1kHz
    Av_dispdata[136] = (u8)(20*log10((double)Av_Afmea[2]) * 255 / 50);  // 10kHz
    Av_dispdata[204] = (u8)(20*log10((double)Av_Afmea[3]) * 255 / 50);  // 100kHz
    Av_dispdata[210] = (u8)(20*log10((double)Av_Afmea[4]) * 255 / 50);  // 120kHz
    Av_dispdata[215] = (u8)(20*log10((double)Av_Afmea[5]) * 255 / 50);  // 140kHz
    Av_dispdata[220] = (u8)(20*log10((double)Av_Afmea[6]) * 255 / 50);  // 160kHz
    Av_dispdata[224] = (u8)(20*log10((double)Av_Afmea[7]) * 255 / 50);  // 180kHz
    Av_dispdata[228] = (u8)(20*log10((double)Av_Afmea[8]) * 255 / 50);  // 200kHz
    Av_dispdata[275] = (u8)(20*log10((double)Av_Afmea[9]) * 255 / 50);  // 1MHz

    // 分段线性插值（调整为276点范围）
    for (i=0; i<69; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[0] + (s32)((s32)(Av_dispdata[68]-Av_dispdata[0]) * i / 68));
    }
    for (i=69; i<137; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[68] + (s32)((s32)(Av_dispdata[136]-Av_dispdata[68]) * (i-68) / 68));
    }
    for (i=137; i<205; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[136] + (s32)((s32)(Av_dispdata[204]-Av_dispdata[136]) * (i-136) / 68));
    }
    for (i=205; i<211; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[204] + (s32)((s32)(Av_dispdata[210]-Av_dispdata[204]) * (i-204) / 6));
    }
    for (i=211; i<216; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[210] + (s32)((s32)(Av_dispdata[215]-Av_dispdata[210]) * (i-210) / 5));
    }
    for (i=216; i<221; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[215] + (s32)((s32)(Av_dispdata[220]-Av_dispdata[215]) * (i-215) / 5));
    }
    for (i=221; i<225; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[220] + (s32)((s32)(Av_dispdata[224]-Av_dispdata[220]) * (i-220) / 4));
    }
    for (i=225; i<229; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[224] + (s32)((s32)(Av_dispdata[228]-Av_dispdata[224]) * (i-224) / 4));
    }
    for (i=229; i<276; i++){
        Av_dispdata[i] = (u8)((s32)Av_dispdata[228] + (s32)((s32)(Av_dispdata[275]-Av_dispdata[228]) * (i-228) / 47));
    }
}

// 故障分析
typedef struct {
    uint32_t Vout_av;
    uint32_t Iin_Vpp;
    uint32_t Vout_Vpp;
    double Rin;
    double bias_100;
    double bias_200k;
    int class;

} Data;

Data data[] = {
    {1157,508,460,1.94,1,1,0},
    {234,131,10,9.42,0.03,0.02,1},
    {1782,1814,12,0.05,0.25,0.54,2},
    {2577,1683,13,0.11,0.29,0.31,3},
    {231,170,9,7.11,0.03,0.02,4},
    {342,1942,9,0.018,0.25,1.0,5},
    {234,1948,9,0.0154,0.26,2.0,6},
    {187,501,10,2.01,0.038,0.03,7},
    {2605,1838,13,0.04,0.34,0.73,8},
    {1159,21,12,62.85,0.03,0.02,9},
    {1153,175,15,6.94,0.06,0.03,10},
    {1157,510,458,1.93,1,1.4,11},
    {0,0,0,0,0,0,12},
    {1132,542,492,1.77,1.73,1.03,13},
    {1158,513,453,1.92,1,0.76,14}
};

#define CLASS_COUNT (sizeof(data)/sizeof(data[0]))  // 自动计算类别数量

// 故障分析
void errordetect(void)
{

    double minDistance = 1e18;
    class_type = 0;

    // 计算输入特征（增加除零保护）
    double Rin = (Iin_Vpp != 0) ? (double)Vin_Vpp / Iin_Vpp : 0.0;
    double bias_100 = (Av_100_n != 0) ? (double)Av_100 / Av_100_n : 0.0;
    double bias_200k = (Av_200k_n != 0) ? (double)Av_200k / Av_200k_n : 0.0;

    // 1. 计算每个特征的最小值和最大值（用于归一化）
    double min[6], max[6];
    // 初始化最小值为数据中第一个元素的特征值
    min[0] = max[0] = data[0].Vout_av;
    min[1] = max[1] = data[0].Iin_Vpp;
    min[2] = max[2] = data[0].Vout_Vpp;
    min[3] = max[3] = data[0].Rin;
    min[4] = max[4] = data[0].bias_100;
    min[5] = max[5] = data[0].bias_200k;

    // 遍历所有数据找到每个特征的极值
    for (int i = 0; i < CLASS_COUNT; i++) {
        double features[6] = {
            data[i].Vout_av,
            data[i].Iin_Vpp,
            data[i].Vout_Vpp,
            data[i].Rin,
            data[i].bias_100,
            data[i].bias_200k
        };
        for (int j = 0; j < 6; j++) {
            if (features[j] < min[j]) min[j] = features[j];
            if (features[j] > max[j]) max[j] = features[j];
        }
    }

    // 2. 对每个特征范围进行保护（避免除零）
    for (int j = 0; j < 6; j++) {
        if (max[j] - min[j] < 1e-6) {
            max[j] = min[j] + 1e-6;  // 确保范围不为零
        }
    }

    // 3. 计算归一化后的距离
    for (int i = 0; i < CLASS_COUNT; i++) {
        // 对每个特征进行归一化 (x - min)/(max - min)
        double norm_Vout_av = (Vout_av - min[0]) / (max[0] - min[0]);
        double norm_Iin_Vpp = (Iin_Vpp - min[1]) / (max[1] - min[1]);
        double norm_Vout_Vpp = (Vout_Vpp - min[2]) / (max[2] - min[2]);
        double norm_Rin = (Rin - min[3]) / (max[3] - min[3]);
        double norm_bias100 = (bias_100 - min[4]) / (max[4] - min[4]);
        double norm_bias200k = (bias_200k - min[5]) / (max[5] - min[5]);

        // 数据集中样本的归一化特征
        double data_norm[6] = {
            (data[i].Vout_av - min[0]) / (max[0] - min[0]),
            (data[i].Iin_Vpp - min[1]) / (max[1] - min[1]),
            (data[i].Vout_Vpp - min[2]) / (max[2] - min[2]),
            (data[i].Rin - min[3]) / (max[3] - min[3]),
            (data[i].bias_100 - min[4]) / (max[4] - min[4]),
            (data[i].bias_200k - min[5]) / (max[5] - min[5])
        };

        // 计算归一化后的欧几里得距离平方（省略开方，不影响比较结果）
        double distance =
            (norm_Vout_av - data_norm[0]) * (norm_Vout_av - data_norm[0]) +
            (norm_Iin_Vpp - data_norm[1]) * (norm_Iin_Vpp - data_norm[1]) +
            (norm_Vout_Vpp - data_norm[2]) * (norm_Vout_Vpp - data_norm[2]) +
            (norm_Rin - data_norm[3]) * (norm_Rin - data_norm[3]) +
            (norm_bias100 - data_norm[4]) * (norm_bias100 - data_norm[4]) +
            (norm_bias200k - data_norm[5]) * (norm_bias200k - data_norm[5]);

        if (distance < minDistance) {
            minDistance = distance;
            class_type = data[i].class;
        }
    }
}